/*
 * @Description:
 * @Author: fhw
 * @Date: 2023-01-04 16:14:27
 */
import { defineComponent, reactive, ref, onMounted, computed, PropType } from 'vue'
import './style.scss'
interface PageState {
	boxToTop: number
	thumb: number
	maxToTop: number
	moveTop: null | number
	top: number
	rate: number
	drag: boolean
	up: string
	down: string
}
const props = {
	height: { type: String as PropType<string>, default: '100%' },
	width: { type: String as PropType<string>, default: '100%' },
} as const
export default defineComponent({
	props,
	emits: ['scroll'],
	setup(props, { slots, emit }) {
		onMounted(() => {
			pageState.boxToTop = document.getElementById('mia-scroll')?.offsetTop ?? 0
			init()
		})
		const thumbH = computed(() => pageState.thumb + 'px')
		const thumbTop = computed(() => pageState.top + 'px')
		const miaScroll = ref<HTMLElement>()
		const pageState = reactive<PageState>({
			boxToTop: 0,
			thumb: 0,
			maxToTop: 0,
			moveTop: null,
			top: 0,
			rate: 1,
			drag: false,
			up: '',
			down: '',
		})
		function init() {
			miaScroll.value?.addEventListener('wheel', onScroll)
			const h_before = miaScroll.value?.clientHeight ?? 0 //框高度
			const h_after = miaScroll.value?.scrollHeight ?? 0 //实际内容高度
			const rate = h_before / h_after
			let thumb = rate < 1 ? rate * h_before : 0
			const maxToTop = h_before - thumb
			if (rate < 1) {
				thumb = rate * h_before
				window.addEventListener('mouseup', onMouseup)
				window.addEventListener('mousemove', onMousemove)
			} else {
				thumb = 0
			}
			pageState.rate = rate
			pageState.thumb = thumb
			pageState.maxToTop = maxToTop
		}
		//页面滚动
		function onScroll() {
			pageState.top = (miaScroll.value?.scrollTop ?? 0) * pageState.rate //计算滚动条所在的高度
			emit('scroll', miaScroll)
		}
		function onMousedown() {
			pageState.drag = true
			pageState.moveTop = null
		}
		function onMouseup(e: { clientY: number; preventDefault: () => void }) {
			if (pageState.drag) {
				if (pageState.moveTop !== null) {
					const speed = e.clientY - pageState.boxToTop - pageState.moveTop
					const top = pageState.top + speed
					scrollThumb(top)
				}
				pageState.moveTop = e.clientY - pageState.boxToTop
			}
			e.preventDefault()
		}
		function scrollThumb(top: string | number) {
			if (top < 0) {
				top = 0
			} else if (top > pageState.maxToTop) {
				top = pageState.maxToTop
			}
			pageState.top = Number(top)
			miaScroll.value && (miaScroll.value.scrollTop = Number(top) / pageState.rate)
		}
		function onMousemove(e: { clientY: number; preventDefault: () => void }) {
			if (pageState.drag) {
				if (pageState.moveTop !== null) {
					const speed = e.clientY - pageState.boxToTop - pageState.moveTop
					const top = pageState.top + speed
					scrollThumb(top)
				}
				pageState.moveTop = e.clientY - pageState.boxToTop
			}
			e.preventDefault()
		}
		return () => (
			<div class="mia-scroll" id="mia-scroll" style={{ height: props.height }}>
				<div class="mia-scroll-box" ref={miaScroll}>
					{slots.default && slots.default()}
				</div>
				{pageState.rate < 1 && (
					<div class="mia-scroll-bar-box">
						<div
							class="mia-scroll-bar"
							style={{ height: thumbH.value, top: thumbTop.value }}
							onMousedown={onMousedown}
							onMouseup={onMouseup}
						></div>
					</div>
				)}
			</div>
		)
	},
})
